/**
 * 默认的 xml标记 处理对象
 * @public
 */
function DefaultTag()
{
}
var $p = DefaultTag.prototype;

$p.namespaceURI = "";
/**
 * @protected
 */
$p.Element = function(context, node)
{
	context.printIndent();
	context.print("<");
	context.print(node.tagName);
	var attrs = node.attributes;

	for (var i = 0; i < attrs.length; i++)
	{
		var attr = attrs.item(i);
		this.Attribute(context, attr)
	}
	var nl = node.childNodes;

	if (nl == null || nl.length == 0)
	{
		context.println("/>");
	}
	else
	{
		context.print(">");
		context.depth++;

		for (var i = 0; i < nl.length; i++)
		{
			context.output(nl.item(i))
		}
		context.depth--;
		context.printIndent();
		context.print("</");
		context.print(node.tagName);
		context.println(">");
	}
}

var xmlns = /^xmlns$|^xmlns:/
/**
 * @protected
 */
$p.Attribute = function(context, node)
{
	var value = context.evalText(node.value);

	if (value == null || value == "")
	{
		return
	}

	if (xmlns.test(node.name))
	{
		var tag = context.getTaglib(value);

		if (tag)
		{
			value = tag.realNamespaceURI || value;
		}
	}
	context.print(" ");
	context.print(node.name);
	context.print('="');
	context.print(context.encodeAttribute(value));
	context.print('"');
}
/**
 * @protected
 */
$p.Text = function(context, node)
{
	context.print(context.encodeText(context.evalText(node.data)));
}
/**
 * @protected
 */
$p.CDATASection = function(context, node)
{
	context.print("<![CDATA[");
	context.print(context.evalText(node.data));
	context.print("]]>");
}

/**
 * @protected
 */
$p.EntityReference = function(context, node)
{
}
/**
 * @protected
 */
$p.Entity = function(context, node)
{
}
/**
 * @protected
 */
$p.ProcessingInstruction = function(context, node)
{
	context.print("<?");
	context.print(node.nodeName);
	context.print(" ");
	context.print(node.data + "?>");
}
/**
 * @protected
 */
$p.Comment = function(context, node)
{
	context.print("<!--");
	context.print(context.encodeText(node.data));
	context.print("-->");
}
/**
 * @protected
 */
$p.Document = function(context, node)
{
	for (var n = node.firstChild; n != null; n = n.nextSibling)
	{
		context.output(n);
	}
}
/**
 * @protected
 */
$p.DocumentType = function(context, node)
{
	if (node.xml)
	{
		context.print(node.xml);
	}
	else
	{
		if (node.publicId)
		{
			context.print("<!DOCTYPE ");
			context.print(node.nodeName);
			context.print(' PUBLIC "');
			context.print(node.publicId);
			context.print('" "');
			context.print(node.systemId);
			context.print('">');
		}
		else
		{
			context.print("<!DOCTYPE ");
			context.print(node.nodeName);
			context.print("[");
			context.print(node.internalSubset);
			context.print("]>");
		}
	}
}
/**
 * @protected
 */
$p.DocumentFragment = function(context, node)
{
	var nl = node.childNodes;

	for (var i = 0; i < nl.length; i++)
	{
		context.output(nl.item(i))
	}
}
/**
 * @protected
 */
$p.Notation = function(context, node)
{
}

function AbstractTag()
{
}

AbstractTag.prototype = new DefaultTag();
AbstractTag.prototype.Element = function(context, node)
{
	var localName = node.localName || node.baseName;

	if (this[localName]instanceof Function)
	{
		this[localName](context, node);
	}
	else
	{
		DefaultTag.prototype.Element.apply(this, context, node);
	}
}

function XHTMLTag()
{
}
XHTMLTag.prototype = new AbstractTag();
XHTMLTag.prototype.namespaceURI = "http://www.xidea.org/taglib/xhtml";
XHTMLTag.prototype.realNamespaceURI = "http://www.w3.org/1999/xhtml";

var htmlLeaf = /^meta$|^link$|^img$|^br$|^hr$/i;
/**
 * @protected
 */
XHTMLTag.prototype.Element = function(context, node)
{
	context.printIndent();
	context.print("<");
	context.print(node.tagName);
	var attrs = node.attributes;

	for (var i = 0; i < attrs.length; i++)
	{
		var attr = attrs.item(i);
		this.Attribute(context, attr)
	}
	var nl = node.childNodes;

	if (nl == null || nl.length == 0)
	{
		if (htmlLeaf.test(node.tagName))
		{ //for html
			context.println("/>");
		}
		else
		{
			context.println(">");
			context.print("</");
			context.print(node.tagName);
			context.println(">");
		}
	}
	else
	{
		context.print(">");
		context.depth++;

		//fix opera bug
		if (node.tagName.toUpperCase() == "SCRIPT")
		{
			for (var i = 0; i < nl.length; i++)
			{
				var c = nl.item(i);

				if (c.nodeType == 4)
				{ //NODE_CDATA_SECTION
					if (/^[\s$]*\/\//.test(c.data))
					{
						context.print("//");
					}
				}
				context.output(c);
			}
		}
		else
		{
			for (var i = 0; i < nl.length; i++)
			{
				context.output(nl.item(i));
			}
		}
		context.depth--;
		context.printIndent();
		context.print("</");
		context.print(node.tagName);
		context.println(">");
	}
}

function VarStatus(items)
{
	this.items = items;
	this.end = this.items.length - 1;
	this.current = this.items[0];
	this.count = this.items.length;
	this.index = this.begin;
	this.last = this.count == 1;
}

$p = VarStatus.prototype;
$p.begin = 0;
$p.step = 1;
$p.first = true;

$p.next = function()
{
	this.index++;
	this.first = false;
	this.last = this.index + 1 >= this.count;
	this.current = this.items[this.index];
}

function CoreTag()
{
}
CoreTag.prototype = new AbstractTag();
CoreTag.prototype.namespaceURI = "http://www.xidea.org/taglib/core";
/*
getBegin()
getCount()
getCurrent()
getEnd()
getIndex()
getStep()
is$p.isLast()
*/


CoreTag.prototype.forEach = function(context, node)
{
	var items = node.getAttribute("items")
		, varStatus = node.getAttribute("varStatus")
		, id = node.getAttribute("var")
		, status
		, valueStack = context.valueStack;
	items = context.evalText(items);
	if (varStatus)
	{
		status = new VarStatus(items);
		valueStack.setVariable(varStatus, status);
	}

	if (items)
	{
		if (! items.hasNext || ! items.next)
		{
			items = new Iterator(items);
		}

		while (items.hasNext())
		{
			try
			{
				var item = items.next();

				if (id)
				{
					valueStack.setVariable(id, item);
				}
				else
				{
					valueStack.push(item);
				}
				var nl = node.childNodes;

				for (var j = 0; j < nl.length; j++)
				{
					context.output(nl.item(j));
				}
			}
			finally
			{
				if (! id)
					valueStack.pop();
				if (status)
					status.next();
			}
		}
	}
}
CoreTag.prototype["if"] = function(context, node)
{
	var test = node.getAttribute("test");
	test = context.evalText(test);
	context.valueStack.setVariable("if", test);

	if (test)
	{
		var nl = node.childNodes;

		for (var j = 0; j < nl.length; j++)
		{
			context.output(nl.item(j))
		}
	}
}
CoreTag.prototype["elseif"] = function(context, node)
{
	var test = context.valueStack.getVariable("if");

	if (test)
	{
		this["if"](context, node);
	}
}
CoreTag.prototype["else"] = function(context, node)
{
	var test = context.valueStack.getVariable("if");

	if (! test)
	{
		var nl = node.childNodes;

		for (var j = 0; j < nl.length; j++)
		{
			context.output(nl.item(j))
		}
	}
}
CoreTag.prototype.choose = function(context, node)
{
	try
	{
		context.valueStack.push(
		{
			choose: false
		});

		var nl = node.childNodes;

		for (var j = 0; j < nl.length; j++)
		{
			context.output(nl.item(j));
		}
	}
	finally
	{
		context.valueStack.pop();
	}
}

CoreTag.prototype.include = function(context, node)
{
	try
	{
		var path = node.getAttribute("path");
		var xpath = node.getAttribute("xpath");
		context.valueStack.push({});
	}
	finally
	{
		context.valueStack.pop();
	}
}

CoreTag.prototype.when = function(context, node)
{
	var test = context.valueStack.getVariable("choose");

	if (! test)
	{
		var test = node.getAttribute("test");
		test = context.evalText(test);
		context.valueStack.setVariable("choose", test);

		if (test)
		{
			var nl = node.childNodes;

			for (var j = 0; j < nl.length; j++)
			{
				context.output(nl.item(j))
			}
		}
	}
}
CoreTag.prototype.otherwise = function(context, node)
{
	var test = context.valueStack.getVariable("choose");

	if (! test)
	{
		var nl = node.childNodes;

		for (var j = 0; j < nl.length; j++)
		{
			context.output(nl.item(j))
		}
	}
}
CoreTag.prototype.script = function(context, node)
{
	with (context)
	{
		with (context.valueStack.context)
		{
			var nl = node.childNodes;

			for (var j = 0; j < nl.length; j++)
			{
				var t = nl.item(j);

				if (t.nodeType == 3 || t.nodeType == 4)
				{ //    case 3: //NODE_TEXT case 4: //NODE_CDATA_SECTION
					eval(t.data);
				}
			}
		}
	}
}

CoreTag.prototype.out = function(context, node)
{
	var esc = context.evalBoolean(node.getAttribute("escapeXml"));
	var value = node.getAttribute("value") || "";

	if (value)
	{
		try
		{
			value = context.evalText(value)
		}
		catch (e)
		{
			value = "";
		}
	}

	if (! value && (value = node.getAttribute("default")))
	{
		try
		{
			value = context.evalText(value)
		}
		catch (e)
		{
			value = "";
		}
	}

	if (esc)
	{
		value = context.encodeText(value);
	}
	context.print(value);
}
/**
 * eg:&lt;c:set var="bookId" value="${param.Remove}"/&gt;
 */
CoreTag.prototype.set = function(context, node)
{
	var value = node.getAttribute("value");
	value = context.evalText(value);
	context.valueStack.setVariable(node.getAttribute("var"), value);
}